#include "ConnectionManager.h"


// Constructor
ConnectionManager::ConnectionManager(HANDLE hReady) {
	this->mutex = CreateMutex(NULL, FALSE, LPCTSTR("NetworkManager"));
	this->hReady = hReady;

	this->head = this->curr = NULL;
}

// Deconstructor
ConnectionManager::~ConnectionManager() {
	Connection *slider = this->head;
	Connection *tmp;

	while(slider != NULL) {
		slider->settings.del("isAlive");
		DWORD lpExitCode = 0;
		GetExitCodeThread((HANDLE)slider->thread, &lpExitCode);
		if(lpExitCode == STILL_ACTIVE) {
//			printf("waiting for thread to end\n");
			WaitForSingleObject((HANDLE)slider->thread, 200);
//			printf("deleting connection\n");
		}

		closesocket(slider->socket);
		tmp = slider;

		slider = slider->next;
		delete tmp;
	}
}


// Add a new Connection
Connection* ConnectionManager::add() {
	Connection *slider = this->head;

	// This will be the first Connection
	if(slider == NULL) {
		this->head = new Connection(this->mutex, this->hReady);
		this->head->prev = NULL;
		this->head->next = NULL;

		slider = this->head;
	}
	// Not the first Connection, add to end of list
	else {
		// advanced till slider is the last node
		while(slider->next != NULL) {
			slider = slider->next;
		}
		// At end of list, attach new Connection
		slider->next = new Connection(this->mutex, this->hReady);
		slider->next->prev = slider;
		slider->next->next = NULL;

		slider = slider->next;
	}

	// set initial values

	// Return a pointer to the new Connection
	return slider;
}

// Del the specified Connection
bool ConnectionManager::del(Connection *conn) {
	Connection *slider = this->head;

	if(slider == NULL) {
		return false;
	}

	while(slider != NULL) {
		if(slider == conn) {
			break;
		}
		slider = slider->next;
	}

	if(slider == NULL) {
		return false;
	}

	if(slider == this->head) {
		this->head = slider->next;
		if(this->head != NULL) {
			this->head->prev = NULL;
		}
	}
	else {
		if(slider->prev != NULL) {
			slider->prev->next = slider->next;
		}
		if(slider->next != NULL) {
			slider->next->prev = slider->prev;
		}
	}

	// causes thread to end, just in case this hasn't already occured
	slider->settings.del("isAlive");
	DWORD lpExitCode = 0;
	GetExitCodeThread((HANDLE)slider->thread, &lpExitCode);
	if(lpExitCode == STILL_ACTIVE) {
//		printf("waiting for thread to end\n");
		WaitForSingleObject((HANDLE)slider->thread, 200);
//		printf("deleting connection\n");
	}
	closesocket(slider->socket);

	// adjust curr if necessary
	if(this->curr == slider) {
		this->curr = slider->next;
	}

	// free up resources
	delete slider;

	return true;
}


// used to loop through the connections
Connection* ConnectionManager::getNext() {
	Connection *slider = this->curr;

	if(this->curr != NULL) {
		this->curr = this->curr->next;
	}

	return slider;
}

// reset getNext() back to first node
void ConnectionManager::reset() {
	this->curr = this->head;
}